//************************************************
//  Filename      : first_level.v                             
//  Author        : Kingstacker                  
//  Company       : School                       
//  Email         : kingstacker_work@163.com     
//  Device        : Altera cyclone4 ep4ce6f17c8  
//  Description   :  iir first_level;16bit in,16bit out.                            
//************************************************
module  first_level #(parameter WIDTH = 16)(
    //input;
    input    wire    clk,
    input    wire    rst_n,
    input    wire    signed [WIDTH-1:0] xin,
    //output;
    output   reg     signed [WIDTH-1:0] yout 
);
localparam B0 =  16'sd1640,
           B1 =  16'sd1280,
           B2 =  16'sd1640,
           A1 = -16'sd2_8925,
           A2 =  16'sd1_3987;
reg signed [WIDTH-1:0] xin1;
reg signed [WIDTH-1:0] xin2;
wire signed [WIDTH-1:0] xin1_w;
wire signed [WIDTH-1:0] xin2_w;
wire signed [31:0] mul_0; 
wire signed [31:0] mul_1; 
wire signed [31:0] mul_2; 
wire signed [33:0] xsum;
reg signed [WIDTH-1:0] yin1;
reg signed [WIDTH-1:0] yin2;
wire signed [WIDTH-1:0] yin1_w;
wire signed [WIDTH-1:0] yin2_w;
wire signed [31:0] mul_3;
wire signed [31:0] mul_4;
wire signed [32:0] ysum;
wire signed [33:0] ysult;
wire signed [33:0] ydiv;
wire signed [WIDTH-1:0] yin;
assign xin1_w = xin1;
assign xin2_w = xin2;
assign yin1_w = yin1;
assign yin2_w = yin2;
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        xin1 <= 0;
        xin2 <= 0;
    end //if
    else begin
        xin1 <= xin;    
        xin2 <= xin1;    
    end //else
end //always
//mul_1 inst;
mul_1  mul_1_u1( 
    .dataa                (B0),
    .datab                (xin),
    .result               (mul_0)
);
mul_1  mul_1_u2( 
    .dataa                (B1),
    .datab                (xin1_w),
    .result               (mul_1)
);
mul_1  mul_1_u3( 
    .dataa                (B2),
    .datab                (xin2_w),
    .result               (mul_2)
);
assign xsum  = mul_0 + mul_1 + mul_2;
//
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        yin1 <= 0;
        yin2 <= 0;
    end //if
    else begin
        yin1 <= yin;
        yin2 <= yin1;    
    end //else
end //always
mul_1  mul_1_u4( 
    .dataa                (A1),
    .datab                (yin1_w),
    .result               (mul_3)
);
mul_1  mul_1_u5( 
    .dataa                (A2),
    .datab                (yin2_w),
    .result               (mul_4)
);
assign ysum  = mul_3 + mul_4;
assign ysult = xsum - ysum;   
assign ydiv  = {{14{ysult[33]}},ysult[33:14]}; 
assign yin = ((~rst_n)? 16'd0 : ydiv[16:1]);
always @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
        yout <= 0;
    end //if
    else begin
        yout <= yin;    
    end //else
end //always

endmodule